<%@Page Language="VB" %>
<%@Import Namespace="System.Xml" %>
<%@Import Namespace="System.Xml.Xpath" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head>
<title>Accessing XML documents using an XPathNavigator</title>
<!-- #include file="..\global\style.inc" -->
</head>
<body bgcolor="#ffffff">
<span class="heading">Accessing XML documents using an XPathNavigator</span><hr />
<!--------------------------------------------------------------------------->

<div id="outDocURL" runat="server"></div>
<div id="outError" runat="server">&nbsp;</div>
<div id="outResults" runat="server"></div>

<script language="vb" runat="server">

Sub Page_Load()

   'create physical path to booklist.xml sample file (in same folder as ASPX page)
   Dim strCurrentPath As String = Request.PhysicalPath
   Dim strXMLPath As String = Left(strCurrentPath, InStrRev(strCurrentPath, "\")) & "booklist.xml"

   'declare a variable to hold an XMLDocument object
   Dim objXMLDoc As New XmlDocument

   Try

      'create a new XpathDocument object and load the XML file
      objXMLDoc.Load(strXMLPath)
      outDocURL.innerHTML = "Loaded file: <b>" & strXMLPath & "</b>"

   Catch objError As Exception

      'display error details
      outError.innerHTML = "<b>* Error while accessing document</b>.<br />" _
          & objError.Message & "<br />" & objError.Source
      Exit Sub  ' and stop execution

   End Try

   'now ready to parse the XML document
   'it must be well-formed to have loaded without error
   'create a new XPathNavigator object using the XMLDocument object
   Dim objXPNav As XPathNavigator = objXMLDoc.CreateNavigator()

   'move the current position to the root #document node
   objXPNav.MoveToRoot()

   'call a recursive function to iterate through all the nodes in the
   'XPathNavigator, creating a string that is placed in the <div> above
   outResults.innerHTML = GetXMLDocFragment(objXPNav, 0)

End Sub


Function GetXMLDocFragment(objXPNav As XPathNavigator, intLevel As Integer) As String

  Dim strNodes As String = ""
  Dim intLoop As Integer

  'display information about this node
  strNodes = strNodes & GetIndent(intLevel) _
           & GetNodeType(objXPNav.NodeType) & ": <b>" & objXPNav.Name _
           & "</b>&nbsp; value=<b>" & objXPNav.Value & "</b><br />"

  'see if this node has any Attributes
  If objXPNav.HasAttributes Then

     'move to the first attribute
     objXPNav.MoveToFirstAttribute()

     Do

       'display the information about it
       strNodes = strNodes & GetIndent(intLevel + 1) _
                & GetNodeType(objXPNav.NodeType) & ": <b>" & objXPNav.Name _
                & "</b>&nbsp; value=<b>" & objXPNav.Value & "</b><br />"

     Loop While objXPNav.MoveToNextAttribute()

     'then move back to the parent node (i.e. the element itself)
     objXPNav.MoveToParent()

  End If

  'see if this node has any child nodes
  If objXPNav.HasChildren Then

     'move to the first child node of the current node
     objXPNav.MoveToFirstChild()

     Do
       'recursively call this function to display the child node fragment
       strNodes = strNodes & GetXMLDocFragment(objXPNav, intLevel + 1)
     Loop While objXPNav.MoveToNext()

     'move back to the parent node - the node we started from when we
     'moved to the first child node - could have used Push and Pop instead
     objXPNav.MoveToParent()

  End If

  'must repeat the process for the remaining sibling nodes (i.e.nodes
  'at the same 'level' as the current node within the XML document
  'so repeat while we can move to the next sibling node
  Do While objXPNav.MoveToNext()

     'recursively call this function to display this sibling node
     'and its atributes and child nodes
     strNodes = strNodes & GetXMLDocFragment(objXPNav, intLevel)

  Loop

  Return strNodes  'pass the result back to the caller

End Function


Function GetIndent(intLevel As Integer)
  'returns a string of non-breaking spaces used to indent each line
  Dim strIndent As String = ""
  Dim intIndent As Integer
  For intIndent = 0 To intLevel
    strIndent = strIndent & "&nbsp; &nbsp; &nbsp; "
  Next
  Return strIndent
End Function

Function GetNodeType(intType As Integer) As String
   'returns the node type as a string
   Select Case (intType)
     Case 0: Return "NONE"
     Case 1: Return "ELEMENT"
     Case 2: Return "ATTRIBUTE"
     Case 3: Return "TEXT"
     Case 4: Return "CDATA SECTION"
     Case 5: Return "ENTITY REFERENCE"
     Case 6: Return "ENTITY"
     Case 7: Return "PROCESSING INSTRUCTION"
     Case 8: Return "COMMENT"
     Case 9: Return "DOCUMENT"
     Case 10: Return "DOCUMENT TYPE"
     Case 11: Return "DOCUMENT FRAGMENT"
     Case 12: Return "NOTATION"
     Case 13: Return "WHITESPACE"
     Case 14: Return "SIGNIFICANT WHITESPACE"
     Case 15: Return "END ELEMENT"
     Case 16: Return "END ENTITY"
     Case 17: Return "XML DECLARATION"
     Case 18: Return "NODE (ALL)"
     Case Else: Return "UNKNOWN"
   End Select
End Function

</script>

<!--------------------------------------------------------------------------->
<!-- #include file="..\global\foot.inc" -->
</body>
</html>
